package kim.artemis.rpc.core.protocol.client;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ConcurrentHashMap;

/**
 * 客户端连接池
 * @author Wq.
 */
@Slf4j
public class ArtemisRpcClientConnectionPool {

    /**
     * 客户端会话集合
     */
    private static volatile ConcurrentHashMap<String, ArtemisRpcClientSession> clientSessionMap;

    /**
     * 客户端会话锁集合
     */
    private static volatile ConcurrentHashMap<String, Object> clientSessionLockMap = new ConcurrentHashMap<>();

    /**
     * 获取客户端会话池
     * @param socketAddress
     * @param artemisRpcReferenceBean
     * @return
     * @throws Exception
     */
    public static ArtemisRpcClientSession getClientSessionPool (String socketAddress, final ArtemisRpcReferenceBean artemisRpcReferenceBean) throws Exception {

        // 初始化会话集合
        if (null == clientSessionMap) {
            synchronized (ArtemisRpcClientSession.class) {
                if (null == clientSessionMap) {
                    clientSessionMap = new ConcurrentHashMap<>();
                }
            }
        }

        ArtemisRpcClientSession clientSession = clientSessionMap.get(socketAddress);
        if (null != clientSession && clientSession.isActive()) {
            return clientSession;
        }

        Object clientLock = clientSessionLockMap.get(socketAddress);
        if (null == clientLock) {
            clientSessionLockMap.putIfAbsent(socketAddress, new Object());
            clientLock = clientSessionLockMap.get(socketAddress);
        }

        synchronized (clientLock) {
            clientSession = clientSessionMap.get(socketAddress);
            if (null != clientSession && clientSession.isActive()) {
                return clientSession;
            }

            if (null != clientSession) {
                clientSession.close();
                clientSessionMap.remove(socketAddress);
            }
            clientSession = ArtemisRpcClientSession.class.newInstance();
            clientSession.initClient(socketAddress, artemisRpcReferenceBean.getSerializer(), artemisRpcReferenceBean.getInvokerFactory());
            clientSessionMap.put(socketAddress, clientSession);
        }
        return clientSession;
    }


}
